<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>PL/Tcl 函数和参数</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="pltcl-overview.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="pltcl.html">快退</a></td><td width="60%" align="center" valign="bottom">章38. PL/Tcl - Tcl 过程语言</td><td width="10%" align="right" valign="top"><a href="pltcl.html">快进</a></td><td width="10%" align="right" valign="top"><a href="pltcl-data.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="PLTCL-FUNCTIONS">38.2. PL/Tcl 函数和参数</a></h1>
<p>要用 PL/Tcl 语言创建一个函数，使用标准的 <a href="sql-createfunction.html"><i>CREATE FUNCTION</i></a> 语法：</p>
<pre class="PROGRAMLISTING">CREATE FUNCTION <tt class="REPLACEABLE"><i>funcname</i></tt> (<tt class="REPLACEABLE"><i>argument-types</i></tt>) RETURNS <tt class="REPLACEABLE"><i>return-type</i></tt> AS $$
    # PL/Tcl 函数体
$$ LANGUAGE pltcl;</pre>
<p>PL/TclU 是一样的，除了语言应该声明为 <tt class="LITERAL">pltclu</tt> 之外。</p>
<p>函数体就是一段 Tcl 代码。当在一个查询里面调用这个函数，参数是作为变量 <tt class="LITERAL">$1</tt> ... <tt class="LITERAL">$<tt class="REPLACEABLE"><i>n</i></tt></tt> 传递给 Tcl 脚本的。结果是用通常的方法从 Tcl 代码中返回的，就是用一个 <tt class="LITERAL">return</tt> 语句。</p>
<p>比如，一个简单的返回两个整数值中较大值的函数可以这样定义：</p>
<pre class="PROGRAMLISTING">CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {$1 &gt; $2} {return $1}
    return $2
$$ LANGUAGE pltcl STRICT;</pre>
<p>请注意 <tt class="LITERAL">STRICT</tt> 子句，它让我们可以不用考虑输入为 NULL 的情况：如果传递了一个 NULL ，该函数实际上就不会被调用，而只是自动返回一个 NULL 结果。</p>
<p>如果是一个不严格的函数且一个参数的实际值是 NULL ，那么对应的 <tt class="LITERAL">$<tt class="REPLACEABLE"><i>n</i></tt></tt> 变量将被设置为一个空字符串。要检测一个特定的参数是否为 NULL ，可以使用 <tt class="LITERAL">argisnull</tt> 函数。比如，假设要求 <code class="FUNCTION">tcl_max</code> 在一个参数为 null 而另外一个为非 null 时返回非 null 参数，而不是 NULL ：</p>
<pre class="PROGRAMLISTING">CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {[argisnull 1]} {
        if {[argisnull 2]} { return_null }
        return $2
    }
    if {[argisnull 2]} { return $1 }
    if {$1 &gt; $2} {return $1}
    return $2
$$ LANGUAGE pltcl;</pre>
<p>如上所述，要从 PL/Tcl 函数中返回一个 NULL 数值，可以执行 <tt class="LITERAL">return_null</tt> 。不管函数是否严格，都可以这么做。</p>
<p>复合类型的参数是当做 Tcl 数组传递给过程的。数组中的元素名字就是复合类型里的属性名字。如果在实际的行中某个属性为 NULL 数值，那它就不会在数组中出现。下面是一个例子：</p>
<pre class="PROGRAMLISTING">CREATE TABLE employee (
    name text,
    salary integer,
    age integer
);

CREATE FUNCTION overpaid(employee) RETURNS boolean AS $$
    if {200000.0 &lt; $1(salary)} {
        return "t"
    }
    if {$1(age) &lt; 30 &#38;&#38; 100000.0 &lt; $1(salary)} {
        return "t"
    }
    return "f"
$$ LANGUAGE pltcl;</pre>
<p>目前没有返回复合类型结果的支持。也不支持返回结果集。</p>
<p>PL/Tcl 目前还不是完全支持域类型：它看待域类型和下层的标量类型是一样的。这就意味着与域关联的约束将不会被强制。对于函数参数，这不是什么问题，但是如果你把 PL/Tcl 函数声明为返回一个域类型，那么就有危险。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="pltcl-overview.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="pltcl-data.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">概述</td><td width="34%" align="center" valign="top"><a href="pltcl.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">PL/Tcl 里的数据值</td></tr>
</table>
</div>
</body></html>